﻿#define _CRT_SECURE_NO_WARNINGS


//#include<iostream>
//using namespace std;
//
//class Example
//{
//private:
//	int _x;
//	int _y;
//public:
//	//构造函数
//	Example(int x = 1, int y = 1)
//	{
//		_x = x;
//		_y = y;
//	}
//	//err
//	//成员函数第一个形参隐含this指针
//	//参数列表就是【类，cout】，不符合我们使用习惯以及代码可读性
//	/*void operator<<(ostream& out)
//	{
//		out << "(_x,_y)=" << "(" << _x << "," << _y << ")" << endl;
//	}*/
//
//	//使用友元函数
//	//ostream& out 只可以使用引用，ostream类不支持拷贝
//	friend ostream& operator<<(ostream& out, const Example& e);
//};
//
////类外使用友元函数
//ostream& operator<<(ostream& out, const Example& e)
//{
//	out << "(_x,_y) = " << "(" << e._x << "," << e._y << ")" << endl;
//	return out;
//}
//
//int main()
//{
//	Example e1(2, 2);
//	Example e2(6, 6);
//	/*cout << e1;
//	cout << e2;*/
//
//	//<<从左向右结合，只需要给一个返回值对象cout就可以了~作为下一次的左操作数
//	cout << e1 << e2;
//	return 0;
//}
//
//#include<iostream>
//using namespace std;
//
//class Example
//{
//private:
//	int _x;
//	int _y;
//public:
//	//构造函数
//	Example(int x = 1, int y = 1)
//	{
//		_x = x;
//		_y = y;
//	}
//	friend ostream& operator<<(ostream& out, const Example& e);
//	friend istream& operator>>(istream& in, Example& e);
//};
//
////类外使用友元函数
//ostream& operator<<(ostream& out, const Example& e)
//{
//	out << "(_x,_y) = " << "(" << e._x << "," << e._y << ")" << endl;
//	return out;
//}
//
//istream& operator>>(istream& in, Example& e)
//// Example& e 不能加const，我们需要向里面写内容，是修改了的
//{
//	cout << "请输入x、y：" << endl;
//	in >> e._x >> e._y;
//	return in;
//}
//int main()
//{
//	Example e1(2, 2);
//	Example e2(6, 6);
//	cout <<"最开始：" << e1 << e2;
//	cin >> e1 >> e2;
//	cout << "cin后：" << e1 << e2;
//	return 0;
//}

//#include<iostream>
//using namespace std;
//
//class Example
//{
//private:
//	int _x;
//	int _y;
//public:
//	//全缺省构造函数——也可以叫默认构造函数
//	Example(int x = 1, int y = 1)
//	{
//		_x = x;
//		_y = y;
//	}
//	//运算符重载==
//	//== 有两个操作对象，但是这里成员函数隐含一个this指针
//	//严格匹配规则，左侧运算对象传给第⼀个参数(this指针）
//	// 右侧运算对象传给第二个参数e
//
//	bool operator== (const Example& e)
//		//传参使用引用，减少拷贝次数
//		//const 修饰，不希望被修改
//	{
//		return _x == e._x && _y == e._y;
//	}
//};
//
//int main()
//{
//	Example e1(1, 1);
//	Example e2(2, 2);
//	//运算符==重载
//	if (e1 == e2)//这种写法更加方便
//	//if (e1.operator==(e2))
//		//也可以像第二种这样显示写
//	{
//		cout << "e1 == e2" << endl;
//	}
//	else
//	{
//		cout << "e1 != e2" << endl;
//	}
//	return 0;
//}
//

//
//#include<iostream>
//using namespace std;
//
//class Example
//{
//private:
//	int _x;
//	int _y;
//public:
//	//构造函数
//	Example(int x = 1, int y = 1)
//	{
//		_x = x;
//		_y = y;
//	}
//
//	//e3 = e2 = e1;
//	//引用返回，减少拷贝次数
//	//Example& operator=(const Example& e)//第一个形参隐含this指针~
//	//{
//	//	if (this != &e)//如果不是自己给自己赋值，就进行赋值操作~
//	//	{
//	//		_x = e._x;
//	//		_y = e._y;
//	//	}
//	//	return *this;//返回第一个，可以进行新的赋值
//	//}
//	friend ostream& operator<<(ostream& out, const Example& e);
//	friend istream& operator>>(istream& in, Example& e);
//};
//
////类外使用友元函数
//ostream& operator<<(ostream& out, const Example& e)
//{
//	out << "(_x,_y) = " << "(" << e._x << "," << e._y << ")" << endl;
//	return out;
//}
//
//istream& operator>>(istream& in, Example& e)
//// Example& e 不能加const，我们需要向里面写内容，是修改了的
//{
//	cout << "请输入x、y：" << endl;
//	in >> e._x >> e._y;
//	return in;
//}
//int main()
//{
//	//int a = 1;
//	//int b = 2;
//	//b = a;//使用赋值运算符改变已经初始化的变量
//	
//	/*cout << "a:" << a << endl;
//	cout << "b:" << b << endl;*/
//
//	Example e1(1, 1);
//	Example e2(2, 2);
//	
//	Example e3 = e2;//这里是拷贝构造~
//	e3  = e2 = e1;//这里是赋值~
//	//自己不显示写也是可以的，这里的例子成员变量都是内置类型~
//	cout << "e1:" << e1 << endl;
//	cout << "e2:" << e2 << endl;
//	cout << "e3:" << e3 << endl;
//	return 0;
//}



#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:
	//构造函数
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		}
		_capacity = n;
		_top = 0;
	}
	//涉及资源，需要显示写拷贝构造函数
	Stack(const Stack& st)
	{
		// 需要对_a指向资源创建同样大的资源再拷贝
		_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败!!!");
			return;
		}

		memcpy(_a, st._a, sizeof(STDataType) * st._top);
		_top = st._top;
		_capacity = st._capacity;
	}

	//涉及资源，需要显示写赋值运算符重载
	//st3 = st1
	Stack& operator=(const Stack& st)
	{
		//if (this != &st)//不能自己给自己赋值
		//{
			//避免原来的st3空间不够，释放原来的空间，开辟与st3一样大的空间
			free(_a);
			_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);//开辟与st1一样大的空间
			if (_a == nullptr)
			{
				perror("malloc fail");
				exit(1);//开辟失败，退出程序
			}
			memcpy(_a, st._a, sizeof(STDataType) * st._top);//把st1上的值拷贝给st3
			_top = st._top;
			_capacity = st._capacity;
		//}
		return *this;//返回
	}

	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			}
			_a = tmp;
			_capacity = newcapacity;
		}
		_a[_top++] = x;
	}
	//析构函数
	~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}

private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};

// 两个Stack实现队列
class MyQueue
{
public:
private:
	Stack pushst;
	Stack popst;
};
int main()
{
	Stack st1;
	st1.Push(1);
	st1.Push(2);
	// 如果Stack不显示实现拷贝构造，那么会使用编译器自动生成的拷贝构造完成浅拷贝
	// 会导致st1和st2里面的_a指针指向同⼀块资源，析构时会析构两次，程序崩溃
	Stack st2 = st1;//拷贝构造

	Stack st3;
	st3.Push(9);

	st3 = st1;//使用赋值运算符重载

	st2 = st2;//自己给自己赋值

	MyQueue mq1;
	// MyQueue自动生成的拷贝构造，会自动调用Stack拷贝构造完成pushst/popst
	// 的拷贝，只要Stack拷贝构造实现了深拷贝，就没问题~
	MyQueue mq2 = mq1;
	return 0;
}